package com.stars.easyms.base.listener.spring;

import com.stars.easyms.base.event.EasyMsConfigChange;
import com.stars.easyms.base.event.EasyMsConfigChangeEvent;
import com.stars.easyms.base.listener.EasyMsConfigChangeListener;
import com.stars.easyms.base.util.ReflectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * <p>className: EasyMsSpringValueChangeListener</p>
 * <p>description: EasyMs实现@Value注解自动刷新监听器</p>
 *
 * @author guoguifang
 * @version 1.7.3
 * @date 2021/3/22 12:22 下午
 */
public class EasyMsSpringValueChangeListener implements EasyMsConfigChangeListener {

    private static final Logger logger = LoggerFactory.getLogger(EasyMsSpringValueChangeListener.class);

    @Override
    public void listen(EasyMsConfigChangeEvent configChangeEvent) {
        for (Map.Entry<String, EasyMsConfigChange> entry : configChangeEvent.getConfigChangeMap().entrySet()) {
            List<EasyMsSpringValueContext> easyMsSpringValueContexts = EasyMsSpringValueRegister.REGISTRY.get(entry.getKey());
            if (easyMsSpringValueContexts != null) {
                easyMsSpringValueContexts.forEach(this::updateValue);
            }
        }
    }

    private void updateValue(EasyMsSpringValueContext easyMsSpringValueContext) {
        MethodParameter methodParameter = easyMsSpringValueContext.getMethodParameter();
        if (methodParameter != null && methodParameter.getMethod() != null) {
            try {
                Object value = EasyMsSpringValueResolveUtil.resolvePropertyValue(easyMsSpringValueContext, true);
                methodParameter.getMethod().invoke(easyMsSpringValueContext.getBean(), value);
            } catch (Exception e) {
                logger.error("Config auto refresh fail, current method: {}!", ReflectUtil.getMethodFullName(methodParameter.getMethod()), e);
            }
        }
        Field field = easyMsSpringValueContext.getField();
        if (field != null) {
            boolean accessible = field.isAccessible();
            if (!accessible) {
                field.setAccessible(true);
            }
            try {
                Object value = EasyMsSpringValueResolveUtil.resolvePropertyValue(easyMsSpringValueContext, false);
                field.set(easyMsSpringValueContext.getBean(), value);
            } catch (Exception e) {
                logger.error("Config auto refresh fail, current field: {}!", field.getDeclaringClass().getName() + "." + field.getName(), e);
            } finally {
                if (!accessible) {
                    field.setAccessible(false);
                }
            }
        }
    }

}